package cd.cdyb.sms.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("ALL")
@Configuration
public class OAuth2Configuration {

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Resource
        private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

        @Resource
        private CustomLogoutSuccessHandler customLogoutSuccessHandler;


        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            DefaultOAuth2ExceptionRenderer rendererPlus = new DefaultOAuth2ExceptionRenderer() {
                @Override
                public Map<String, Object> getExceptionMap(String oAuth2ErrorCode, String oAuth2ErrorMessage) {
                    Map<String, Object> modelsResult = new LinkedHashMap<>();
                    modelsResult.put("code", "error");
                    modelsResult.put("errorMessage", "没有权限访问");
                    modelsResult.put("data", "");
                    return modelsResult;
                }
            };

            DefaultOAuth2ExceptionRenderer rendererloginPlus = new DefaultOAuth2ExceptionRenderer() {
                @Override
                public Map<String, Object> getExceptionMap(String oAuth2ErrorCode, String oAuth2ErrorMessage) {
                    Map<String, Object> modelsResult = new LinkedHashMap<>();
                    modelsResult.put("code", "error");
                    modelsResult.put("errorMessage", "loginOut");
                    modelsResult.put("data", "");
                    return modelsResult;
                }
            };
            MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
            List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
            messageConverters.add(messageConverter);
            rendererPlus.setMessageConverters(messageConverters);
            rendererloginPlus.setMessageConverters(messageConverters);

            //异常处理
            OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
            entryPoint.setExceptionRenderer(rendererloginPlus);
            resources.authenticationEntryPoint(entryPoint);

            //权限处理
            OAuth2AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler();
            accessDeniedHandler.setExceptionRenderer(rendererPlus);
            resources.accessDeniedHandler(accessDeniedHandler);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {


            http.cors().and()
                    .logout()
                    .logoutUrl("/oauth/logout")
                    .logoutSuccessHandler(customLogoutSuccessHandler)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/*/pmall/**").permitAll().anyRequest().authenticated();;


            //自定义权限
//            http.authorizeRequests().antMatchers("/user/wu").hasAnyAuthority("P00001");

//            http.authorizeRequests().anyRequest().authenticated();
            ;

        }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        private static final String ENV_OAUTH = "authentication.oauth.";
        private static final String PROP_CLIENTID = "clientid";
        private static final String PROP_SECRET = "secret";
        private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds";


/*        @Autowired
        private DataSource dataSource;*/

        @Resource
        private RedisConnectionFactory redisConnectionFactory;

        @Bean
        public TokenStore tokenStore() {
            RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);

            redisTokenStore.setAuthenticationKeyGenerator(new RandomAuthenticationKeyGenerator());
            return redisTokenStore;

        }

/*
        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }
*/

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            //允许url访问client
            oauthServer.allowFormAuthenticationForClients();

        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {
            endpoints
                    .tokenStore(tokenStore())
                    .authenticationManager(authenticationManager);
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.withClientDetails(new DefaultClientDetailsServiceImpl());

/*            clients
                    .inMemory()
                    .withClient(propertyResolver.getProperty(PROP_CLIENTID))
                    .scopes("read", "write")
                    .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
                    .authorizedGrantTypes("password", "refresh_token")
                    .secret(propertyResolver.getProperty(PROP_SECRET))
                    .accessTokenValiditySeconds(propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800));*/
        }


    }

}
